package com.lingjtx.common.influx.factory;

import com.lingjtx.common.core.util.StringUtil;
import com.lingjtx.common.influx.annotation.InfluxMapper;
import com.lingjtx.common.influx.config.InfluxProperties;
import com.lingjtx.common.thread.config.ObjectPoolTemplateConfig;
import com.lingjtx.common.thread.pooling.ObjectPoolTemplate;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.Ordered;
import org.springframework.core.env.Environment;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.stereotype.Component;

import java.net.http.HttpClient;

/**
 * InfluxMapperScannerRegistrar 与 InfluxMapperScanner 功能一模一样，只是 mapper 加载方式不一样
 * InfluxMapperScannerRegistrar 是通过注解 EnableInfluxMapperScan 来扫描 xml 和 mapper 接口
 * InfluxMapperScanner 是通过 spring 配置文件加载
 */
@Component
public class InfluxMapperScanner implements BeanDefinitionRegistryPostProcessor, EnvironmentAware {

    private Environment environment;

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        String basePackages = environment.getProperty("spring.influx.basePackages");

        if (StringUtil.isNotEmpty(basePackages)) {
            ClassPathScanningCandidateComponentProvider scanner =
                    new ClassPathScanningCandidateComponentProvider(false) {
                        @Override
                        protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
                            return true; // 放开限制
                        }
                    };
            scanner.addIncludeFilter(new AnnotationTypeFilter(InfluxMapper.class));

            String[] basePackagesArr = basePackages.split(",");
            for (String basePackage : basePackagesArr) {
                for (BeanDefinition bd : scanner.findCandidateComponents(basePackage)) {
                    try {
                        String className = bd.getBeanClassName();
                        Class<?> mapperInterface = Class.forName(className);

                        BeanDefinitionBuilder builder =
                                BeanDefinitionBuilder.genericBeanDefinition(InfluxMapperFactoryBean.class);
                        builder.addConstructorArgValue(mapperInterface);

                        if (StringUtil.isNotEmpty(className)) {
                            registry.registerBeanDefinition(className, builder.getBeanDefinition());
                        }

                    } catch (ClassNotFoundException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }
}
